#ifndef __SG_PCL_EUCLIDEAN_CLUSTER_H__
#define __SG_PCL_EUCLIDEAN_CLUSTER_H__

#include "SGPCLJsonConfig.h"

#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/extract_clusters.h>

namespace sgpcl
{

/// <summary>
/// 去噪算法参数(基于平均距离）
/// </summary>
struct SGEuclideanClusterConfig : public SGPCLJsonConfig
{
  int nMinClusterSize;     // 簇最小尺寸
  float fClusterTolerance; // 簇生长距离

  SGPCL_API SGEuclideanClusterConfig();

  SGPCL_API ~SGEuclideanClusterConfig() = default;

  /// <summary>
  /// 解析Json字符串，读取参数
  /// </summary>
  /// <param name="sJsonRoot">Json节点</param>
  SGPCL_API void ParseJson(const rapidjson::Value& sJsonRoot) final override;
};

template <typename PointT>
std::vector<pcl::PointIndices> EuclideanCluster(
  typename pcl::PointCloud<PointT>::ConstPtr spCloud, const SGEuclideanClusterConfig& sConfig)
{
  // 计时器
  SG_TIMER("欧式聚类");

  pcl::EuclideanClusterExtraction<PointT> ec;     // 欧式聚类对象
  ec.setClusterTolerance(sConfig.fClusterTolerance);                // 设置近邻搜索的搜索半径为2cm

  ec.setMinClusterSize(sConfig.nMinClusterSize); // 设置一个聚类需要的最少的点数目为100

  pcl::search::KdTree<PointT>::Ptr spTree(new pcl::search::KdTree<PointT>);
  spTree->setInputCloud(spCloud);
  ec.setSearchMethod(spTree); // 设置点云的搜索机制

  ec.setInputCloud(spCloud);

  std::vector<pcl::PointIndices> cluster_indices; // 存储各簇的索引号
  ec.extract(cluster_indices); // 从点云中提取聚类，并将点云索引保存在cluster_indices中

  return cluster_indices;
}

}

#endif // __SG_PCL_EUCLIDEAN_CLUSTER_H__
